Day 8 我們已經寫好一支 Python 程式,可以自動取得 server01 的:
CPU
Memory
Disk
Top CPU Processes
執行:
python collect_info.py
就可以產生:
incident.json
不過目前還有一個問題。
還是要有人自己執行 Python。
如果收到 High CPU 告警之後,我還要先登入 Server,再手動執行程式,那其實還不能算真正的自動化。
所以今天要把前面兩條流程接起來。
今天要做到什麼?
目前我們有兩條分開的流程。
第一條是監控:
server01
↓
Prometheus
↓
Grafana
↓
High CPU Alert
第二條是:
python collect_info.py
↓
收集 CPU / Memory / Disk / Process
↓
incident.json
今天要把它們接成:
Grafana Alert
↓
Webhook
↓
FastAPI
↓
collect_info.py
↓
incident.json
也就是:
Grafana 發現異常後,自己通知 Python 開始收集資料。
Step 1:準備 FastAPI
先登入 server01:
進入昨天建立的專案:
cd ~/aiops
啟用 Virtual Environment:
source venv/bin/activate
安裝 FastAPI 和 Uvicorn:
pip install fastapi uvicorn
這次 FastAPI 的用途很單純。
我們需要一個網址,讓 Grafana 可以把 Alert 傳過來。
例如:
http://192.168.1.101:8000/grafana-alert
當這個網址收到告警,就執行昨天的:
collect_info.py
Step 2:建立 Webhook Receiver
在 ~/aiops 裡建立:
nano app.py
加入:
from fastapi import FastAPI, Request
import subprocess
import sys
from datetime import datetime
app = FastAPI()
@app.post("/grafana-alert")
async def grafana_alert(request: Request):
payload = await request.json()
status = payload.get("status")
print(
f"[{datetime.now()}] "
f"Grafana Alert Status: {status}"
)
if status == "firing":
subprocess.run(
[
sys.executable,
"collect_info.py"
]
)
return {
"status": "ok",
"message": "System information collected"
}
return {
"status": "ok",
"message": "Alert received"
}
這段程式其實沒有很複雜。
它只做三件事:
收到 Grafana Webhook
↓
確認是不是 Firing
↓
執行 collect_info.py
目前我們只在:
status = firing
的時候執行資料收集。
如果收到的是:
resolved
就先不做任何事情。
Step 3:啟動 FastAPI
在:
~/aiops
下面執行:
uvicorn app:app --host 0.0.0.0 --port 8000
正常的話會看到:
Uvicorn running on http://0.0.0.0:8000
代表 FastAPI 已經開始等待 Grafana 的 Webhook。
現在架構變成:
server01
Port 8000
│
▼
FastAPI
│
▼
collect_info.py
目前先讓 Terminal 保持開著即可。
正式環境當然不會一直用 Terminal 跑,之後再處理 Service 或 Docker。
今天先確認流程跑得起來。
Step 4:先不要急著接 Grafana
跟 Day 7 測試通知時一樣,我還是想先分段測試。
先從 Monitoring Server 手動送一個假的 Firing Alert:
curl -X POST
http://192.168.1.101:8000/grafana-alert
-H "Content-Type: application/json"
-d '{"status":"firing"}'
如果成功,FastAPI 會回:
{
"status": "ok",
"message": "System information collected"
}
接著回到 server01:
ls -l ~/aiops
應該可以看到昨天的:
incident.json
已經被重新產生。
打開看看:
cat incident.json
裡面應該還是:
{
"hostname": "server01",
"cpu": 35.2,
"memory": 48.3,
"disk": 36.1,
"top_processes": []
}
代表現在已經做到:
HTTP Request
↓
FastAPI
↓
Python Collector
↓
incident.json
這段沒有問題之後,才開始接 Grafana。
Step 5:把 Webhook 加進 Grafana
回到 Grafana。
進入:
Alerting → Contact points
Day 7 已經建立過 Discord 的 Contact Point。
這次可以另外新增一個 Webhook Integration。
Webhook URL 填入:
http://192.168.1.101:8000/grafana-alert
Method:
POST
設定完成之後,可以先使用:
Test
測試。
如果 server01 上的 FastAPI Terminal 出現 Request 紀錄,代表:
Grafana
↓
FastAPI
已經打通了。
如果主機有開 UFW,不建議直接把 8000 Port 對所有來源開放。這個 Lab 只需要讓 Monitoring Server 可以連進來即可。
Step 6:測試真正的 High CPU Alert
最後才測試真正的 Alert。
目前我們的規則是:
Server01 High CPU
正常設定可能是:
CPU > 90%
持續 5 分鐘
實驗時可以暫時把 Threshold 調低。
例如:
CPU > 20%
持續 1 分鐘
讓 Alert 比較容易進入:
Normal
↓
Pending
↓
Firing
當狀態真的變成:
Firing
這次除了 Discord 收到:
Server01 High CPU
FastAPI 也會收到 Webhook。
接著自動執行:
python collect_info.py
最後產生:
incident.json
現在終於不用自己執行 Python
Day 8 的流程是:
收到 Alert
↓
登入 Server
↓
手動執行
python collect_info.py
今天變成:
CPU 異常
↓
Grafana 判斷 Firing
↓
Webhook
↓
FastAPI
↓
Python 自動執行
↓
收集故障資訊
這就是這個系列第一次真正把:
監控
跟
自動化
串在一起。
Day 9 完成
今天完成:
✓ 安裝 FastAPI
✓ 建立 Webhook Endpoint
✓ 接收 Grafana Alert
✓ 判斷 Firing 狀態
✓ 自動執行 collect_info.py
✓ 產生 incident.json
目前整套架構已經變成:
server01
│
│ Metrics
▼
Prometheus
↓
Grafana
│
├── Discord Notification
│
└── Webhook
↓
FastAPI
↓
collect_info.py
↓
incident.json
這個版本還很簡單。
但現在至少做到一件以前需要人工完成的事情:
告警發生後,系統自己開始做第一輪資料收集。
接下來還缺什麼?
現在 incident.json 已經有:
CPU
Memory
Disk
Process
可是如果 Server 真正發生問題,我通常還會需要另一種資訊:
Log。
例如 CPU 高的同一個時間,是不是剛好有 Service Error?
Application 有沒有 Exception?
系統有沒有發生其他異常?
所以接下來要補上這一塊。